package glashart2xmltv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
 * 
 * @author Jeroen Peschier
 * @version $Id: Grabber.java 2 2013-02-09 11:54:47Z peschierj@gmail.com $
 */
public class Grabber {
	
	public static final int MAX_DAY_SEGMENTS = 8;
	private static final String ENCODING = "UTF-8";
	private static Log log = LogFactory.getLog(Grabber.class);
	
	public Map<String, Collection<GuideEntry>> getBaseGuideEntries(Date date, int daySegment) throws Exception {
		HttpClient client = new DefaultHttpClient();
	    try {
			Map<String, Collection<GuideEntry>> entries = null;
	    	String baseUrl = Config.getInstance().getBaseUrl();
	    	String url = baseUrl + "/epgdata." + asString(date) + "." + daySegment + ".json.gz";
	    	log.debug("Fetching guide entries for offset [" + daySegment + "] from [" + url + "].");
	        HttpGet get = new HttpGet(url);
	        HttpResponse response = client.execute(get);
	        HttpEntity entity = response.getEntity();
	        if (entity != null) {
	        	try {
		        	InputStream compressedStream = new GZIPInputStream(entity.getContent());
		        	Reader reader = new BufferedReader(new InputStreamReader(compressedStream, ENCODING));
		        	Gson gson = new Gson();
		        	Type mapType = new TypeToken<Map<String, Collection<GuideEntry>>>(){}.getType();
		        	entries = gson.fromJson(reader, mapType);
	        	} catch (IOException e) {
	        		log.error("Failed to process stream.", e);
	        		entries = Collections.EMPTY_MAP;
	        	}
	        }
	        return entries;
	    } finally {
	        client.getConnectionManager().shutdown();
	    }
	}
	
	private String asString(Date date) {
		return new SimpleDateFormat("yyyyMMdd").format(date);
	}
	
	public ProgrammeEntry getProgrammeInfo(String id) throws Exception {
		HttpClient client = new DefaultHttpClient();
		ProgrammeEntry entry = null;
	    try {
	    	String baseUrl = Config.getInstance().getBaseUrl();
	    	String url = baseUrl + '/' + id.substring(id.length() - 2) + '/' + id + ".json"; 
	        HttpGet get = new HttpGet(url);
	        HttpResponse response = client.execute(get);
	        int statusCode = response.getStatusLine().getStatusCode();
	        if (statusCode == HttpStatus.SC_OK) {
		        HttpEntity entity = response.getEntity();
		        if (entity != null) {
		        	Reader reader = new BufferedReader(new InputStreamReader(entity.getContent(), ENCODING));
		        	Gson gson = new Gson();
		        	entry = gson.fromJson(reader, ProgrammeEntry.class);
		        } 
	        } else {
	        	log.error("Failed to fetch guide entry due to HTTP response code [" + statusCode + "].");
	        }
	        return entry;
	    } finally {
	        client.getConnectionManager().shutdown();
	    }
	}
}